package com.sky.service.admin.impl;

import com.sky.dto.GoodsSalesDTO;
import com.sky.dto.OrderSumDTO;
import com.sky.mapper.admin.ReportMapper;
import com.sky.pojo.Orders;
import com.sky.pojo.UserReport;
import com.sky.service.admin.ReportService;
import com.sky.service.admin.WorkspaceService;
import com.sky.vo.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@Slf4j
@AllArgsConstructor
public class ReportServiceImpl implements ReportService {

    private ReportMapper reportMapper;
    private WorkspaceService workspaceService;

    @Override
    public TurnoverReportVO getTurnover(LocalDate begin, LocalDate end) {
        //获取区间所有的天
        List<LocalDate> allDays = getAllDays(begin, end);
        //按日期查询订单金额，可能会漏天
        List<OrderSumDTO> orderSumDTOs = reportMapper.orderAmountStatistics(begin, end.plusDays(1), Orders.COMPLETE_ORDER);
        List<Double> amountList = new ArrayList<>();
        for (LocalDate oneDay : allDays) {
            Optional<OrderSumDTO> first = orderSumDTOs.stream().filter(orderSumDTO -> orderSumDTO.getOrderDate().equals(oneDay)).findAny();
            if (first.isPresent()) {
                amountList.add(first.get().getAmount());
            } else {
                amountList.add(0d);
            }
        }

        TurnoverReportVO reportVO = new TurnoverReportVO();
        reportVO.setTurnoverList(StringUtils.collectionToCommaDelimitedString(amountList));
        reportVO.setDateList(StringUtils.collectionToCommaDelimitedString(allDays));
        return reportVO;
    }


    @Override
    public UserReportVO userStatistics(LocalDate begin, LocalDate end) {
//        List<LocalDate> allDays = getAllDays(begin, end);
        UserReportVO userReportVO = new UserReportVO();
        /*List<Integer> addList = new ArrayList<>();
        List<Integer> allList = new ArrayList<>();
        for (LocalDate oneDay : allDays) {
            //计算当天新增的用户
            Integer dayAdd = reportMapper.userStatistics(oneDay, oneDay.plusDays(1));
            addList.add(dayAdd);
            //计算当前位为止的总用户
            Integer dayTotal = reportMapper.userStatistics(null, oneDay.plusDays(1));
            allList.add(dayTotal);
        }
        userReportVO.setDateList(StringUtils.collectionToCommaDelimitedString(allDays));
        userReportVO.setNewUserList(StringUtils.collectionToCommaDelimitedString(addList));
        userReportVO.setTotalUserList(StringUtils.collectionToCommaDelimitedString(allList));*/
        List<UserReport> userReports = reportMapper.findUserStatistics(begin, end);
        List<Integer> addList = new ArrayList<>();
        List<Integer> allList = new ArrayList<>();
        List<String> dateList = new ArrayList<>();
        for (UserReport userReport : userReports) {
            addList.add(userReport.getNewUser());
            allList.add(userReport.getTotalUser());
            dateList.add(userReport.getDate());
        }
        userReportVO.setDateList(StringUtils.collectionToCommaDelimitedString(dateList));
        userReportVO.setNewUserList(StringUtils.collectionToCommaDelimitedString(addList));
        userReportVO.setTotalUserList(StringUtils.collectionToCommaDelimitedString(allList));
        return userReportVO;
    }

    @Override
    public OrderReportVO orderStatistics(LocalDate begin, LocalDate end) {
        List<LocalDate> allDays = getAllDays(begin, end);
        //数据库按天查询订单总数及有效订单数,注意：有点天可能没有，表为0
        List<OrderSumDTO> orderSumDTOS = reportMapper.orderStatistics(begin, end.plusDays(1));
        List<Integer> totalList = new ArrayList<>();
        List<Integer> completeList = new ArrayList<>();
        for (LocalDate oneDay : allDays) {
            Optional<OrderSumDTO> first = orderSumDTOS.stream().filter(o -> o.getOrderDate().equals(oneDay)).findAny();
            //当天没有数据，表示0
            if (first.isPresent()) {
                totalList.add(first.get().getTotalNum());
                completeList.add(first.get().getCompleteNum());
            } else {
                totalList.add(0);
                completeList.add(0);
            }
        }

        Integer totalNum = totalList.stream().reduce(Integer::sum).get();
        Integer completeNum = completeList.stream().reduce(Integer::sum).get();
        Double rate = 0d;
        if (totalNum != 0) {
            rate = (double) completeNum / totalNum;
        }
        OrderReportVO reportVO = new OrderReportVO();
        reportVO.setDateList(StringUtils.collectionToCommaDelimitedString(allDays));
        reportVO.setOrderCountList(StringUtils.collectionToCommaDelimitedString(totalList));
        reportVO.setValidOrderCountList(StringUtils.collectionToCommaDelimitedString(completeList));
        reportVO.setValidOrderCount(completeNum);
        reportVO.setTotalOrderCount(totalNum);
        reportVO.setOrderCompletionRate(rate);

        return reportVO;
    }

    @Override
    public SalesTop10ReportVO top10Statistics(LocalDate begin, LocalDate end) {
        List<GoodsSalesDTO> salesDTOS = reportMapper.top10Statistics(begin, end.plusDays(1));
        if (CollectionUtils.isEmpty(salesDTOS)) {
            return new SalesTop10ReportVO();
        }
        List<String> nameList = salesDTOS.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList());
        List<Integer> numberList = salesDTOS.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList());

        SalesTop10ReportVO top10ReportVO = new SalesTop10ReportVO();
        top10ReportVO.setNameList(StringUtils.collectionToCommaDelimitedString(nameList));
        top10ReportVO.setNumberList(StringUtils.collectionToCommaDelimitedString(numberList));
        return top10ReportVO;
    }

    @Override
    public void exportBusinessData(HttpServletResponse response) throws Exception{
        //导出数据，通过模板更改数据就好了
        //1.查询数据
        LocalDate now = LocalDate.now();
        LocalDate begin = now.minusDays(30);
        BusinessDataVO businessDataVO = workspaceService.businessData();
        //2.excel处理步骤
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表.xlsx");
        XSSFWorkbook workbook = new XSSFWorkbook(resourceAsStream);
        XSSFSheet sheet = workbook.getSheetAt(0);
        //处理时间
        XSSFRow timeRow = sheet.getRow(1);
        timeRow.getCell(1).setCellValue("时间" + begin + "至" + now);
        //处理概览数据
        XSSFRow row4 = sheet.getRow(3);
        row4.getCell(2).setCellValue(businessDataVO.getTurnover());//营业额
        row4.getCell(4).setCellValue(businessDataVO.getOrderCompletionRate());//订单完成
        row4.getCell(6).setCellValue(businessDataVO.getNewUsers());//新增用户数
        //获取第五行
        XSSFRow row5 = sheet.getRow(4);
        row5.getCell(2).setCellValue(businessDataVO.getValidOrderCount());//有效订单
        row5.getCell(4).setCellValue(businessDataVO.getUnitPrice());//平均客单价

        LocalDate queryDay = begin;
        Integer index = 0;
        for (int i = 0; i < 30; i++) {
            BusinessDataVO vo = workspaceService.businessData(queryDay, queryDay);
            LocalDate currentDay = queryDay;
            queryDay = queryDay.plusDays(1);
            if(vo == null | vo.getTurnover() ==null){
                index++;
                continue;
            }
            XSSFRow row = sheet.getRow(7 + i - index);
            row.getCell(1).setCellValue(currentDay.toString());
            row.getCell(2).setCellValue(vo.getTurnover());
            row.getCell(3).setCellValue(vo.getValidOrderCount());
            row.getCell(4).setCellValue(vo.getOrderCompletionRate());
            row.getCell(5).setCellValue(vo.getUnitPrice());
            row.getCell(6).setCellValue(vo.getNewUsers());
        }

        workbook.write(response.getOutputStream());
        workbook.close();
    }

    /**
     * 获取区间所有的日期
     *
     * @param begin
     * @param end
     * @return
     */
    public List<LocalDate> getAllDays(LocalDate begin, LocalDate end) {
        List<LocalDate> allDays = new ArrayList<>();
        allDays.add(begin);
        while (!begin.equals(end)) {
            begin = begin.plusDays(1);
            allDays.add(begin);
        }
        return allDays;
    }
}
